<?php

if (!defined(DB_HOST)) {
    define(DB_HOST, 'localhost');
}
if (!defined(DB_PORT)) {
    define(DB_PORT, '3306');
}
if (!defined(DB_USER)) {
    define(DB_USER, 'root');
}
if (!defined(DB_PWD)) {
    define(DB_PWD, '123456');
}
if (!defined(DB_NAME)) {
    define(DB_NAME, 'ron');
}

/**
 * 构造不需要转义的sql语句的类
 *  
 */


class _Sql {

    var $sql_str;

    /**
     *
     * @param string $str  <p>不需要转义的字符串</p>
     */
    function __construct($str) {
        $this->sql_str = $str;
    }

}

class DB {

    /**
     * PDO链接
     * @link http://cn.php.net/manual/zh/class.pdo.php
     * @var PDO 
     * 
     */
    private static $conn = null;

    /**
     * 储存sql语句
     * @var string 
     */
    private static $sql;

    /**
     * 储存由query()或execute()生成的PDOStatement对象
     * @var PDOStatement 
     */
    private static $statement;

    /**
     * 储存fetch()或fecthAll()返回的结果
     * @var mixed 
     */
    private static $result;

    /**
     * 初始化PDO链接 
     */
    private static function init() {
        try {
            self::$conn = new PDO('mysql:dbname=' . DB_NAME . ';host=' . DB_HOST . ';port=' . DB_PORT, DB_USER, DB_PWD, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
        } catch (PDOException $e) {
            self::error("数据库连接初始化错误: " . $e->getMessage() . "<br/>");
        }
    }

    /**
     * 自动连接数据库 
     */
    private static function autoConnect() {
        self::$conn == null ? self::init() : '';
    }

    /**
     * 执行mysql语句，并返回包含结果集的数组
     * @param string $sql
     * @return array 
     */
    public static function query($sql) {
        self::autoConnect();
        return self::$statement = self::$conn->query($sql);
    }

    /**
     * 返回一个_Sql对象，包含不需转义的sql语句
     * @param type $str 包含不需转义的sql语句的字符串
     * @return \_Sql 一个_Sql对象，包含不需转义的sql语句
     */
    public static function sql($str) {
        return new _Sql($str);
    }

    /**
     * 以prepare--execute方式快捷执行sql语句
     * @param string $sql
     * @param array $args
     * @return PDOStatement 
     */
    public static function getList($sql, $args = array()) {
        self::autoConnect();
        self::$statement = self::$conn->prepare($sql);
        self::$statement->execute($args);
        if (!self::$statement->errorCode()) {
            self::error(self::$statement->errorInfo() . '</br>SQL语句：' . self::$sql);
        }
        return self::$statement;
    }

    /**
     * 从一个结果集中获取下一行
     * @return mixed 
     */
    public static function fetch() {
        return self::$result = self::$statement->fetch();
    }

    /**
     * 返回一个数组,其中包含所有结果集的行
     * @param int [$fetch_style]
     * @return array 
     */
    public static function fetchAll($fetch_style = PDO::FETCH_ASSOC) {
        return self::$result = self::$statement->fetchAll($fetch_style);
    }

    /**
     * 快速查询
     * @param string $flieds <p>要查询的字段</p>
     * @param string $table <p>要查询的表名</p>
     * @param mixed $where <p>where后面的条件语句，格式为：'id=? AND username=?'</p> 也可以为_Sql对象，DB::sql('id=10 AND username=NULL'),当为这种形式时，$where_args参数省略
     * @param array $where_args <p>参数，替换$where中的?号</p>
     * @return array 
     */
    public static function select($flieds, $table, $where = '', $where_args = array()) {
        if ($where != '' && !empty($where_args)) {
            self::$sql = 'SELECT ' . $flieds . ' FROM ' . $table . ' where ' . $where;
        } else if ($where != '') {
            if (get_class($where) == '_Sql') {
                self::$sql = 'SELECT ' . $flieds . ' FROM ' . $table . ' where ' . $where->sql_str;
            }
        } else {
            self::$sql = 'SELECT ' . $flieds . ' FROM ' . $table;
        }
        self::getList(self::$sql, $where_args);
        return self::fetchAll();
    }

    /**
     * 快速修改条目
     * @param string $table <p>要进行操作的表名</p>
     * @param array $data   <p>要插入的数据的数组，键名为要插入的字段，值为对应要插入的值</p>
     * @param mixed $where <p>where后面的条件语句，格式为：'id=? AND username=?'</p> 也可以为_Sql对象，DB::sql('id=10 AND username=NULL'),当为这种形式时，$where_args参数省略
     * @param array $where_args <p>参数，替换$where中的?号</p>
     */
    public static function update($table, $data, $where = '', $where_args = array()) {
        //$DB::update('test',array("name"=>$a,"age"=>12),"id=12");

        self::$sql = "UPDATE $table SET ";
        $args = array();
        foreach ($data as $key => $value) {

            if (get_class($value) == '_Sql') {
                self::$sql .=$key . '=' . $value->sql_str;
            } else {
                self::$sql .=$key . '=?';
                next($data) != FALSE ? self::$sql .=',' : self::$sql;
                array_push($args, $value);
            }
        }

        if ($where != '' && !empty($where_args)) {
            self::$sql .=' where ' . $where;
            foreach ($where_args as $value) {
                array_push($args, $value);
            }
        } elseif ($where != '') {
            if (get_class($where) == '_Sql') {
                self::$sql .=' where ' . $where->sql_str;
            }
        }
        self::getList(self::$sql, $args);
    }

    /**
     * 快速插入条目
     * @param string $table <p>要进行操作的表名</p>
     * @param array $data <p>要插入的数据的数组，键名为要插入的字段，值为对应要插入的值</p>
     */
    public static function insert($table, $data) {
        self::$sql = "INSERT INTO $table(";
        $sql_ed = 'VALUES(';
        $args = array();
        foreach ($data as $key => $value) {
            if (get_class($value) == '_Sql') {

                if (next($data) != FALSE) {
                    $sql_ed.=$value->sql_str . ',';
                    self::$sql .=$key . ',';
                } else {
                    $sql_ed.=$value->sql_str . ')';
                    self::$sql .=$key . ')' . $sql_ed;
                }
            } else {

                if (next($data) != FALSE) {
                    $sql_ed.='?,';
                    self::$sql .=$key . ',';
                } else {
                    $sql_ed.='?)';
                    self::$sql .=$key . ')' . $sql_ed;
                }
                array_push($args, $value);
            }
        }
        self::getList(self::$sql, $args);
    }

    /**
     * 快速删除条目
     * @param string $table
     * @param mixed $where
     * @param array $where_args 
     */
    public static function delete($table, $where = '', $where_args = array()) {
        self::$sql = 'DELETE FROM ' . $table;
        if ($where != '' && !empty($where_args)) {
            self::$sql = 'DELETE FROM ' . $table . ' where ' . $where;
        } else if ($where != '') {
            if (get_class($where) == '_Sql') {
                self::$sql = 'DELETE FROM ' . $table . ' where ' . $where->sql_str;
            }
        }
        self::getList(self::$sql, $where_args);
    }

    /**
     * 返回最后插入条目的ID
     * @param string $name
     * @return string <p>返回上次插入操作，主键列类型是自增的最后的自增ID</p>
     */
    public static function insertId($name = NULL) {
        return self::$conn->lastInsertId($name);
    }

    /**
     * 返回sql执行结果中包含的条目数
     * @return int <p>sql执行结果中包含的条目数</p>
     */
    public static function rowsNum() {
        return self::$statement->fetchColumn();
    }

    /**
     * <p>主要是用于PDO::query()和PDO::prepare()进行Delete、Insert、Update操作影响的结果集，对PDO::exec()方法和Select操作可能无效（有些数据库不支持）。</p>
     * @return int 
     */
    public static function rowCount() {
        return self::$statement->rowCount();
    }

    /**
     * 输出调试信息 
     */
    public static function debug() {
        self::$statement->debugDumpParams();
    }

    /**
     * 输出错误信息$msg,并停止当前脚本
     * @param string $msg 
     */
    private static function error($msg) {
        die($msg);
    }

}